package com.yf.openapi.modules.user.controller;


import cn.hutool.core.lang.hash.Hash;
import com.yf.ability.shiro.dto.SysUserLoginDTO;
import com.yf.openapi.modules.user.service.OpenUserService;
import com.yf.system.modules.user.UserUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;


@Api(tags = {"用户接口"})
@Controller
@RequestMapping("/api")
public class OpenUserController {

    @Autowired
    private OpenUserService openUserService;

    /**
     * 同步登录接口
     * @param access
     * @param userId
     * @param userName
     * @param realName
     * @param departs
     * @param role
     * @return
     */
    @ApiOperation(value = "同步信息并登录", notes = "第三方系统通过GET跳转直接请求此URL完成信息同步并登录" +
            "<br>" +
            "<br>接口具备以下特性：" +
            "<br>1、如果用户名userName不存在，则会创建新的用户" +
            "<br>2、如果传入的部门不存在，则会逐级查找并自动创建缺失的部门" +
            "<br>3、userId为非必填字段，默认自动生成id，如果传入则会使用传入的字段作为id，必须保证唯一性" +
            "<br>4、如果用户已存在、则会自动登录，并更新相关信息" +
            "<br>5、如果用户会话已存在，则不会再次登录，直接跳转到回调地址" +
            "<br>" +
            "<br>callback参数说明：" +
            "<br>同域情况：即接口和前端使用同一个域名的情况，一般使用此方式部署" +
            "<br>登录后并跳转到首页：callback参数不填，可以兼容手机和PC的登录跳转" +
            "<br>登录后跳转到指定页面：/#/web/index | /#/web/course | ... 注意：手机端和PC端的页面不一样" +
            "<br><br>非同域情况：即接口和前端部署在不同的域名下，此情况要经过多次跳转才能实现同步登录" +
            "<br>PC端同步登录并跳转到课程页面：https://exam.yfhl.net/#/sync/?token=${token}&to=/web/repo (注意：${token}为固定写法，跳转时自动替换，to参数不能包含#）" +
            "<br>手机端同步登录并跳转课程页面：https://exam.yfhl.net/#/pages/login/sync/?token=${token}&to=/pages/course/index (注意：${token}为固定写法，跳转时自动替换)" +
            "<br>" +
            "<br>完整请求示例：" +
            "<br>直接访问链接：https://exam.yfhl.net/api/open/user/sync?access=xxxxx&userName=zhangsan&realName=张三&departs=云帆互联,技术部&role=student&callback=%2F%23%2Fweb%2Frepo" +
            "<br>参数access获取请参考：授权接口--> 获取授权Access")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "access", value = "授权码，调用接口的凭证，请通过【授权接口】来获得", dataType = "string", paramType = "query", required = true),
            @ApiImplicitParam(name = "userId", value = "第三方用户ID，非必要，如果需要与第三方用户ID保持一致，请传入此值，务必确保全局唯一", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "userName", value = "第三方系统的用户名、也可以是ID，但务必确保全局唯一", dataType = "string", paramType = "query", required = true),
            @ApiImplicitParam(name = "realName", value = "用户姓名", dataType = "string", paramType = "query", required = true),
            @ApiImplicitParam(name = "departs", value = "部门名称，多级部门请用半角逗号隔开，如果部门不存在，会自动创建", dataType = "string", paramType = "query", example = "云帆互联,研发部,技术部", required = true),
            @ApiImplicitParam(name = "role", value = "角色ID，必须是考试系统已存在的角色ID", dataType = "string", paramType = "query", example = "student", required = true),
            @ApiImplicitParam(name = "callback", value = "登录后跳转地址，必须使用URLEncoder，如果URL中包含${token}，则会替换成真实的token值，同域跳转直接传入相对url", dataType = "string", paramType = "query", example = "%2F%23%2Fweb%2Frepo")
    })
    @GetMapping("/api/open/user/sync")
    public ModelAndView syncLogin(
            @RequestParam("access") String access,
            @RequestParam(name = "userId", required = false) String userId,
            @RequestParam("userName") String userName,
            @RequestParam("realName") String realName,
            @RequestParam("departs") String departs,
            @RequestParam("role") String role,
            @RequestParam(name = "callback", required = false) String callback) throws IOException {

        // 登录会话
        String token = null;
        // 跳转时间，默认2
        int sec = 0;

        // 如果已经登录，则直接跳转过去
        if(UserUtils.isLogin()){
            token = UserUtils.token(false);
        }else {
            // 同步登录
            SysUserLoginDTO respDTO = openUserService.syncLogin(userId, userName, realName, role, departs);
            token = respDTO.getToken();
            sec = 2;
        }

        // 写到页面
        ModelAndView mv = new ModelAndView("sync");
        mv.addObject("token", token);
        String url = this.decode(callback, token);
        mv.addObject("callback", url);
        mv.addObject("sec", sec);
        return mv;
    }

    /**
     * 获取返回参数
     * @param access
     * @param userId
     * @param userName
     * @param realName
     * @param departs
     * @param role
     * @param callback
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping("/open/user/sync2")
    public Map<String,Object> synLoginInfo(@RequestParam("access") String access,
                                           @RequestParam(name = "userId", required = false) String userId,
                                           @RequestParam("userName") String userName,
                                           @RequestParam("realName") String realName,
                                           @RequestParam("departs") String departs,
                                           @RequestParam("role") String role,
                                           @RequestParam(name = "callback", required = false) String callback) throws Exception{
        String token = null;
        // 跳转时间，默认2
        int sec = 0;

        // 如果已经登录，则直接跳转过去
        if(UserUtils.isLogin()){
            token = UserUtils.token(false);
        }else {
            // 同步登录
            SysUserLoginDTO respDTO = openUserService.syncLogin(userId, userName, realName, role, departs);
            token = respDTO.getToken();
            sec = 2;
        }
        //返回参数
        Map<String,Object> pageInfo=new HashMap<>();
        pageInfo.put("token",token);
        String url = this.decode(callback, token);
        pageInfo.put("callback",url);
        pageInfo.put("sec", sec);
        return pageInfo;
    }



    /**
     * 获取跳转
     * @param callback
     * @param token
     * @return
     * @throws UnsupportedEncodingException
     */
    private String decode(String callback, String token) throws UnsupportedEncodingException {
        if(!StringUtils.isBlank(callback)){
            String url = URLDecoder.decode(callback, "utf-8");
            return url.replace("${token}", token);
        }
        return "/";
    }
}
